package com.ruoyi.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.ruoyi.business.PortServerIce.QueryServantPrx;
import com.ruoyi.business.PortServerIce.TradeServantPrx;
import com.ruoyi.business.constant.TradeConstants;
import com.ruoyi.business.domain.BusinessTradeConfig;
import com.ruoyi.business.domain.BusinessTradeRecord;
import com.ruoyi.business.dto.*;
import com.ruoyi.business.enumType.PSIceMarket;
import com.ruoyi.business.enumType.PSIceOrderState;
import com.ruoyi.business.enumType.PSIceOrderType;
import com.ruoyi.business.enumType.TriggerType;
import com.ruoyi.business.exception.TradeException;
import com.ruoyi.business.holder.*;
import com.ruoyi.business.mapper.BusinessTradeConfigMapper;
import com.ruoyi.business.mapper.BusinessTradeRecordMapper;
import com.ruoyi.business.service.IBusinessTradeRecordService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysDictDataMapper;
import io.jsonwebtoken.lang.Collections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 交易记录Service业务层处理
 *
 * @author ruoyi
 * @date 2024-04-15
 */
@Service
public class BusinessTradeRecordServiceImpl implements IBusinessTradeRecordService {
    private static final Logger logger = LoggerFactory.getLogger(BusinessTradeRecordServiceImpl.class);


    @Autowired
    private BusinessTradeRecordMapper businessTradeRecordMapper;
    @Autowired
    private BusinessTradeConfigMapper businessTradeConfigMapper;

    @Autowired
    private SysDictDataMapper sysDictDataMapper;

    @Autowired
    private TradeServantPrx tradeServantPrx;

    @Autowired
    private QueryServantPrx queryServantPrx;



    @Value("${trade.rate}")
    private String tradeRate;





    /**
     * 查询交易记录
     *
     * @param id 交易记录主键
     * @return 交易记录
     */
    @Override
    public BusinessTradeRecord selectBusinessTradeRecordById(Long id) {
        return businessTradeRecordMapper.selectBusinessTradeRecordById(id);
    }

    /**
     * 查询交易记录列表
     *
     * @param businessTradeRecord 交易记录
     * @return 交易记录
     */
    @Override
    public List<BusinessTradeRecord> selectBusinessTradeRecordList(BusinessTradeRecord businessTradeRecord) {
        return businessTradeRecordMapper.selectBusinessTradeRecordListWithStrategyName(businessTradeRecord);
    }

    /**
     * 新增交易记录
     *
     * @param businessTradeRecord 交易记录
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult tradeAndInsertBusinessTradeRecord(BusinessTradeRecord businessTradeRecord) {
        String stockCode = businessTradeRecord.getStockCode();
        List<String> stockSplitList = Arrays.asList(stockCode.split("\\."));

        String stockPrefix = stockSplitList.get(0);
        PSIceMarket sh = PSIceMarket.SH;
        if (TradeConstants.SYMBOL_PREFIX_SHSE.equals(stockPrefix)) {
            sh = PSIceMarket.SH;
        } else if (TradeConstants.SYMBOL_PREFIX_SZSE.equals(stockPrefix)) {
            sh = PSIceMarket.SZ;
        } else {
            logger.error("交易标的只能是沪市或者深市股票");
        }
        stockCode = stockSplitList.get(1);
        PSIceOrder psIceOrder = new PSIceOrder(0, null, sh, PSIceOrderType.valueOf(businessTradeRecord.getDelegateType()), stockCode, (long) (businessTradeRecord.getPrice().doubleValue() * 10000), businessTradeRecord.getDelegateVolume(), null);
        PSIceOrderOutHolder psIceOrderOutHolder = new PSIceOrderOutHolder();
        PSIceErrorCodeHolder psIceErrorCodeHolder = new PSIceErrorCodeHolder();

        PSIceAccount psIceAccount = new PSIceAccount();
        psIceAccount.ClientName= businessTradeRecord.getClientName();
        psIceAccount.Password= businessTradeRecord.getPassword();


        int i = tradeServantPrx.SendOrder(psIceAccount, psIceOrder, psIceOrderOutHolder, psIceErrorCodeHolder);
        System.out.println("Received result from server: " + i);
        // 执行成功
        if (i == 0) {
//            PSIceOrderSearch psIceOrderSearch = new PSIceOrderSearch("", psIceOrderOutHolder.value.OrderNo, businessTradeRecord.getStockCode(), 0);
//            PSIceTransStatusListHolder psIceTransStatusListHolder = new PSIceTransStatusListHolder();
//            // 成交
//            PSIceOrderStatusListHolder psIceOrderStatusListHolder = new PSIceOrderStatusListHolder();
//            int i4 = queryServantPrx.GetTodayOrderStatusList(new PSIceAccount(), psIceOrderSearch, psIceOrderStatusListHolder, psIceErrorCodeHolder);
//            // 委托
//            int j = queryServantPrx.GetTodayTransStatusList(new PSIceAccount(), psIceOrderSearch, psIceTransStatusListHolder, psIceErrorCodeHolder);
//            PSIceTransStatus[] value = psIceTransStatusListHolder.value;
//            List<PSIceTransStatus> collect = Arrays.stream(value).filter(a -> a.OrderNo.equals(psIceOrderOutHolder.value.OrderNo)).collect(Collectors.toList());

            businessTradeRecord.setOrderNo(psIceOrderOutHolder.value.OrderNo);
            businessTradeRecord.setCreateTime(new Date());
            businessTradeRecord.setDelegateType(businessTradeRecord.getDelegateType());
            businessTradeRecord.setDelegateState(PSIceOrderState.Undeclared.value());
            businessTradeRecord.setDelegateCancle(false);
            businessTradeRecord.setExchange(sh.value());
            businessTradeRecord.setTradingStatus(1);
            businessTradeRecordMapper.insertBusinessTradeRecord(businessTradeRecord);
            return AjaxResult.success(businessTradeRecord);
        } else {
            businessTradeRecord.setOrderNo(psIceOrderOutHolder.value.OrderNo);
            businessTradeRecord.setCreateTime(new Date());
            businessTradeRecord.setDelegateType(businessTradeRecord.getDelegateType());
            businessTradeRecord.setDelegateState(PSIceOrderState.Undeclared.value());
            businessTradeRecord.setDelegateCancle(false);
            businessTradeRecord.setExchange(sh.value());
            businessTradeRecord.setTradingStatus(0);
            businessTradeRecord.setErrorMsg(psIceErrorCodeHolder.value.Message);
            businessTradeRecordMapper.insertBusinessTradeRecord(businessTradeRecord);
            return AjaxResult.error(psIceErrorCodeHolder.value.Message);
        }
    }

    /**
     * 修改交易记录
     *
     * @param businessTradeRecord 交易记录
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateBusinessTradeRecord(BusinessTradeRecord businessTradeRecord) {
        return businessTradeRecordMapper.updateBusinessTradeRecord(businessTradeRecord);
    }

    /**
     * 批量删除交易记录
     *
     * @param ids 需要删除的交易记录主键
     * @return 结果
     */
    @Override
    public int deleteBusinessTradeRecordByIds(Long[] ids) {
        return businessTradeRecordMapper.deleteBusinessTradeRecordByIds(ids);
    }

    /**
     * 删除交易记录信息
     *
     * @param id 交易记录主键
     * @return 结果
     */
    @Override
    public int deleteBusinessTradeRecordById(Long id) {
        return businessTradeRecordMapper.deleteBusinessTradeRecordById(id);
    }

    @Override
    public AjaxResult cancleOrder(BusinessTradeRecord businessTradeRecord) {


        BusinessTradeRecord businessTradeRecord1 = businessTradeRecordMapper.selectBusinessTradeRecordByOrderNo(businessTradeRecord.getOrderNo());
        if (Objects.isNull(businessTradeRecord1)) {
            throw new RuntimeException("查询原交易数据为空");
        }

        PSIceOrderCancel psIceOrderCancel = new PSIceOrderCancel(PSIceOrderType.valueOf(businessTradeRecord.getDelegateType()), null, 0, businessTradeRecord.getOrderNo(), PSIceMarket.valueOf(businessTradeRecord1.getExchange()), businessTradeRecord1.getStockCode(), 0, null);
        PSIceOrderCancelOutHolder psIceOrderCancelOutHolder = new PSIceOrderCancelOutHolder();


        PSIceAccount psIceAccount = new PSIceAccount();
        psIceAccount.ClientName= businessTradeRecord.getClientName();
        psIceAccount.Password= businessTradeRecord.getPassword();


        PSIceErrorCodeHolder psIceErrorCodeHolder = new PSIceErrorCodeHolder();
        int i = tradeServantPrx.CancelOrder(psIceAccount, psIceOrderCancel, psIceOrderCancelOutHolder, psIceErrorCodeHolder);
        // 执行成功
        if (i == 0) {
//            PSIceOrderSearch psIceOrderSearch = new PSIceOrderSearch("", psIceOrderOutHolder.value.OrderNo, businessTradeRecord.getStockCode(), 0);
//            PSIceTransStatusListHolder psIceTransStatusListHolder = new PSIceTransStatusListHolder();
            // 成交
//            PSIceOrderStatusListHolder psIceOrderStatusListHolder = new PSIceOrderStatusListHolder();
//            int i4 = queryServantPrx.GetTodayOrderStatusList( new PSIceAccount(), psIceOrderSearch,psIceOrderStatusListHolder, psIceErrorCodeHolder);
            // 委托
//            int j = queryServantPrx.GetTodayTransStatusList(new PSIceAccount(), psIceOrderSearch, psIceTransStatusListHolder, psIceErrorCodeHolder);
//            if (j == 0) {
//                PSIceTransStatus[] value = psIceTransStatusListHolder.value;
//                List<PSIceTransStatus> collect = Arrays.stream(value).filter(a -> a.OrderNo.equals(psIceOrderOutHolder.value.OrderNo)).collect(Collectors.toList());
//
//                if (!Collections.isEmpty(collect)) {
//                    PSIceTransStatus psIceTransStatus = collect.get(0);
//                    businessTradeRecord.setStockholderNo(psIceTransStatus.TransNo);
//            businessTradeRecord.setOrderNo(psIceOrderOutHolder.value.OrderNo);
            businessTradeRecord1.setDelegateCancle(true);
            businessTradeRecordMapper.updateBusinessTradeRecord(businessTradeRecord1);
            return AjaxResult.success();
//                }
//            }
        }
        return AjaxResult.error(psIceErrorCodeHolder.value.Message);
    }

    @Override
    public PSIceTransStatus selectCurrentTransTradeOrderByOrderNo(String orderNo,String clientName,String password) {

        PSIceErrorCodeHolder psIceErrorCodeHolder = new PSIceErrorCodeHolder();
        PSIceOrderSearch psIceOrderSearch = new PSIceOrderSearch("", orderNo, "", 1);
        PSIceTransStatusListHolder psIceTransStatusListHolder = new PSIceTransStatusListHolder();

        // 成交

        PSIceAccount psIceAccount = new PSIceAccount();
        psIceAccount.ClientName=clientName;
        psIceAccount.Password= password;

        int j = queryServantPrx.GetTodayTransStatusList(psIceAccount, psIceOrderSearch, psIceTransStatusListHolder, psIceErrorCodeHolder);
        PSIceTransStatus[] value = psIceTransStatusListHolder.value;
        List<PSIceTransStatus> collect = Arrays.stream(value).filter(a -> a.OrderNo.equals(orderNo)).collect(Collectors.toList());
        if (Collections.isEmpty(collect)) {
            return null;
        }
        return collect.get(0);
    }

    @Override
    public PSIceOrderStatus selectCurrentDelegateTradeOrderByOrderNo(String orderNo,String clientName,String password) {
        PSIceErrorCodeHolder psIceErrorCodeHolder = new PSIceErrorCodeHolder();
        PSIceOrderSearch psIceOrderSearch = new PSIceOrderSearch("", orderNo, "", 1);
        PSIceOrderStatusListHolder psIceOrderStatusListHolder = new PSIceOrderStatusListHolder();

        PSIceAccount psIceAccount = new PSIceAccount();
        psIceAccount.ClientName=clientName;
        psIceAccount.Password= password;
        // 委托

        int j = queryServantPrx.GetTodayOrderStatusList(psIceAccount, psIceOrderSearch, psIceOrderStatusListHolder, psIceErrorCodeHolder);
        PSIceOrderStatus[] value = psIceOrderStatusListHolder.value;
        List<PSIceOrderStatus> collect = Arrays.stream(value).filter(a -> a.OrderNo.equals(orderNo)).collect(Collectors.toList());

        if (collect.isEmpty()) {
            return null;
        }
        return collect.get(0);
    }

    @Override
    public List<BusinessTradeRecord> selectTodayTradeRecord() {
        return businessTradeRecordMapper.selectTodayTradeRecord();
    }

    @Override
    public AjaxResult doBusinessTradeByStopProfitOrLoss(Long strategyId, PSIceOrderType psIceOrderType, BusinessTradeRecord businessTradeRecord, BigDecimal price, TriggerType triggerType) {
        // 部分撤单 或 已成交 数据进行止盈止损操作
        if (PSIceOrderState.PartCanceled.value() == businessTradeRecord.getDelegateState() || PSIceOrderState.Filled.value() == businessTradeRecord.getDelegateState()) {
            BusinessTradeRecord stopProfitBusinessRecord = new BusinessTradeRecord();
            // 盘口价下浮1% 卖出 上浮1% 买入
            BigDecimal tradePrice = BigDecimal.ZERO;
            if (PSIceOrderType.Buy.equals(psIceOrderType)) {
                tradePrice = price.multiply(new BigDecimal(tradeRate).multiply(new BigDecimal("0.01")).add(BigDecimal.ONE));
            } else if (PSIceOrderType.Sell.equals(psIceOrderType)) {
                tradePrice = price.multiply(BigDecimal.ONE.subtract(new BigDecimal(tradeRate).multiply(new BigDecimal("0.01"))));
            }
            stopProfitBusinessRecord.setPrice(tradePrice);
            stopProfitBusinessRecord.setStrategyId(strategyId);
            stopProfitBusinessRecord.setStrategyGroupId(businessTradeRecord.getStrategyGroupId());
            stopProfitBusinessRecord.setStockCode(businessTradeRecord.getStockCode());
            stopProfitBusinessRecord.setDelegateType(psIceOrderType.value());
            stopProfitBusinessRecord.setDelegateVolume(businessTradeRecord.getDealVolume());
            stopProfitBusinessRecord.setTriggerType(triggerType.toString());
            stopProfitBusinessRecord.setRelatedOrderNo(businessTradeRecord.getOrderNo());
            stopProfitBusinessRecord.setDelegateCode(businessTradeRecord.getDelegateCode());
            stopProfitBusinessRecord.setPositionClosed(true);
            stopProfitBusinessRecord.setClientName(businessTradeRecord.getClientName());
            stopProfitBusinessRecord.setPassword(businessTradeRecord.getPassword());

            AjaxResult ajaxResult = tradeAndInsertBusinessTradeRecord(stopProfitBusinessRecord);
            if ((int) ajaxResult.get(AjaxResult.CODE_TAG) == 200) {
                businessTradeRecord.setPositionClosed(true);
                businessTradeRecordMapper.updateBusinessTradeRecord(businessTradeRecord);
            }
            return ajaxResult;
        }
        return AjaxResult.error("单据状态为：" + PSIceOrderState.valueOf(businessTradeRecord.getDelegateState()));
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult doBusinessTradeAuto(Long strategyId, PSIceOrderType psIceOrderType, BigDecimal price, BigDecimal open, String symbol, Boolean orFirstTrade, String relatedOrderNo) {

        BusinessTradeConfig businessTradeConfig = businessTradeConfigMapper.selectBusinessTradeConfigById(strategyId);
        if (Objects.isNull(businessTradeConfig)) {
            throw new TradeException("配置策略数据为空");
        }
        if (businessTradeConfig.getStatus() == 1) {
            logger.info("策略禁用，跳过开仓，strategyId：{}", strategyId);
            return AjaxResult.error("策略禁用，跳过开仓");
        }
        String clientName = businessTradeConfig.getClientName();
        String password = businessTradeConfig.getPassword();
        Long strategyGroupId = businessTradeConfig.getStrategyGroupId();
        Long tradeTimesLimit = businessTradeConfig.getTradeTimesLimit();
        BigDecimal tradeAmountLimit = businessTradeConfig.getTradeAmountLimit();
        BigDecimal tradeAmountPerLimit = businessTradeConfig.getTradeAmountPerLimit();
        Long tradeVolumePerLimit = businessTradeConfig.getTradeVolumePerLimit();
        Boolean tradeHedge = businessTradeConfig.getTradeHedge();
//        if (tradeHedge) {
//            if (Objects.isNull(businessTradeConfig.getTradeHedgeSaleAmount())) {
//                return AjaxResult.error("对冲交易做多金额为空");
//            }
//            if (Objects.isNull(businessTradeConfig.getTradeHedgeSellAmount())) {
//                return AjaxResult.error("对冲交易做空金额为空");
//            }
//        }
        //  开仓策略（1：延迟开仓，2：百分比开仓 ，3：信号量开仓）
        Integer openPositionStrategy = businessTradeConfig.getOpenPositionStrategy();

        Integer positionDelayMinute = businessTradeConfig.getPositionDelayMinute();
        BigDecimal openPositionRate = businessTradeConfig.getOpenPositionRate() == null ? null : businessTradeConfig.getOpenPositionRate().divide(new BigDecimal(100), 6, RoundingMode.HALF_UP);
        // 跌幅
        BigDecimal dropExtentRate = null;
        if(StringUtils.isNotEmpty(businessTradeConfig.getOpenPositionSemaphoreStr())){
            OpenPositionSemaphoreDto openPositionSemaphoreDto = JSON.parseObject(businessTradeConfig.getOpenPositionSemaphoreStr(), OpenPositionSemaphoreDto.class);
            if(Objects.nonNull(openPositionSemaphoreDto.getDropExtentRate())){
                dropExtentRate = openPositionSemaphoreDto.getDropExtentRate().divide(new BigDecimal(100), 6, RoundingMode.HALF_UP);
            }
        }

        List<BusinessTradeRecord> businessTradeRecordList = selectTodayTradeRecord();

        // 只校验开仓数据 未平仓数据
        businessTradeRecordList = businessTradeRecordList.stream().filter(item -> TriggerType.AUTO_TAKE_POSITION_TRIGGER.equals(TriggerType.valueOf(item.getTriggerType()))).
                filter(item -> item.getDelegateState() == PSIceOrderState.Undeclared.value()
                        || item.getDelegateState() == PSIceOrderState.Declaring.value() || item.getDelegateState() == PSIceOrderState.Declared.value()
                        || item.getDelegateState() == PSIceOrderState.PendingCancel.value() || item.getDelegateState() == PSIceOrderState.PFPendingCancel.value()
                        || item.getDelegateState() == PSIceOrderState.PartCanceled.value() || item.getDelegateState() == PSIceOrderState.PartFilled.value()
                        || item.getDelegateState() == PSIceOrderState.Filled.value()).collect(Collectors.toList());

        Map<Long, List<BusinessTradeRecord>> strategyRecordMap = businessTradeRecordList.stream().collect(Collectors.groupingBy(BusinessTradeRecord::getStrategyId));
        Date nowTime = DateUtils.dateTime(DateUtils.HH_MM_SS, new SimpleDateFormat(DateUtils.HH_MM_SS).format(new Date()));
        Date openTime = null;
        Date closeTime = null;
        try {
            openTime = DateUtils.parseDate("09:30:00", DateUtils.HH_MM_SS);
            closeTime = DateUtils.parseDate("14:40:00", DateUtils.HH_MM_SS);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (nowTime.after(closeTime)) {
            return AjaxResult.error("14:45:00 后禁止开仓");
        }
        boolean openPosition = false;


        if(orFirstTrade){
            //首次开仓信号校验
            // 百分比开仓
            if (openPositionStrategy==2&&Objects.nonNull(openPositionRate)) {
                // 判断行情是否在延迟时间之后
                if (Objects.nonNull(positionDelayMinute)) {
                    Date openTimeDelay = DateUtils.addMinutes(openTime, positionDelayMinute);
                    if (nowTime.before(openTimeDelay)) {
                        return AjaxResult.error("开仓未到配置的开仓延迟时间");
                    }
                }
                if (price.compareTo(open.multiply(BigDecimal.ONE.add(openPositionRate))) > 0) { //price：0.896，open：0.895，
                    // 上涨
                    psIceOrderType = PSIceOrderType.Buy;
                    openPosition = true;
                    logger.info("触发百分比买入开仓，price：{}，open：{}，dropExtentRate：{}",price,open,openPositionRate);
                }
                if (price.compareTo(open.multiply(BigDecimal.ONE.subtract(openPositionRate))) < 0) {
                    // 下跌
                    psIceOrderType = PSIceOrderType.Sell;
                    openPosition = true;
                    logger.info("触发百分比卖出开仓，price：{}，open：{}，dropExtentRate：{}",price,open,openPositionRate);
                }
            }

            // 信号量 跌幅
            if(openPositionStrategy==3&&Objects.nonNull(dropExtentRate)){
                if (price.compareTo(open.multiply(BigDecimal.ONE.subtract(dropExtentRate))) <= 0) {
                    logger.info("达到跌幅，price：{}，open：{}，dropExtentRate：{}",price,open,dropExtentRate);
                    // 达到跌幅
                    openPosition = true;
                }
            }
            // 延迟开仓
            if(openPositionStrategy==1&&Objects.nonNull(positionDelayMinute)){
                Date openTimeDelay = DateUtils.addMinutes(openTime, positionDelayMinute);
                if (nowTime.before(openTimeDelay)) {
                    return AjaxResult.error("开仓未到配置的开仓延迟时间");
                }
                logger.info("触发延迟开仓，price：{}，positionDelayMinute：{}",price,positionDelayMinute);
                openPosition = true;
            }
        }else {
            openPosition = true;
        }

        if(!openPosition){
            return AjaxResult.error("开仓条件未触发");
        }


        BigDecimal takePositionPrice = BigDecimal.ZERO;
        BigDecimal takePositionPriceRevers = BigDecimal.ZERO;
        PSIceOrderType psIceOrderTypeRevers = null;
        // 对冲金额
        BigDecimal tradeReversAmount = BigDecimal.ZERO;


        // 单次开仓根据价格折算最大 股数
        BigDecimal tradeAmount = tradeAmountPerLimit;
        if (psIceOrderType.equals(PSIceOrderType.Buy)) {
            takePositionPrice = price.multiply(new BigDecimal(tradeRate).multiply(new BigDecimal("0.01")).add(BigDecimal.ONE));
            takePositionPriceRevers = price.multiply(BigDecimal.ONE.subtract(new BigDecimal(tradeRate).multiply(new BigDecimal("0.01"))));
            psIceOrderTypeRevers = PSIceOrderType.Sell;
            if (tradeHedge) {
                // 对冲单做多金额
                tradeAmount = businessTradeConfig.getTradeHedgeSaleAmount();
                tradeReversAmount = businessTradeConfig.getTradeHedgeSellAmount();
                // 如果主单金额和对冲单 开仓金额不为空
                if(Objects.nonNull(businessTradeConfig.getTradeHedgeMainAmount())&&Objects.nonNull(businessTradeConfig.getTradeHedgeAmount())){
                    if(psIceOrderType.equals(PSIceOrderType.valueOf(businessTradeConfig.getFirstPositionType()))){
                        //开仓方向和首单相同
                    tradeAmount = businessTradeConfig.getTradeHedgeMainAmount();
                    tradeReversAmount = businessTradeConfig.getTradeHedgeAmount();
                    }else{
                        tradeAmount = businessTradeConfig.getTradeHedgeAmount();
                        tradeReversAmount = businessTradeConfig.getTradeHedgeMainAmount();
                    }
                }
            }
        } else {
            takePositionPrice = price.multiply(BigDecimal.ONE.subtract(new BigDecimal(tradeRate).multiply(new BigDecimal("0.01"))));
            takePositionPriceRevers = price.multiply(new BigDecimal(tradeRate).multiply(new BigDecimal("0.01")).add(BigDecimal.ONE));
            psIceOrderTypeRevers = PSIceOrderType.Buy;
            if (tradeHedge) {
                // 对冲单做空金额
                tradeAmount = businessTradeConfig.getTradeHedgeSellAmount();
                tradeReversAmount = businessTradeConfig.getTradeHedgeSaleAmount();
                // 如果主单金额和对冲单 开仓金额不为空
                if(Objects.nonNull(businessTradeConfig.getTradeHedgeMainAmount())&&Objects.nonNull(businessTradeConfig.getTradeHedgeAmount())){
                    if(psIceOrderType.equals(PSIceOrderType.valueOf(businessTradeConfig.getFirstPositionType()))){
                        //开仓方向和首单相同
                    tradeAmount = businessTradeConfig.getTradeHedgeMainAmount();
                    tradeReversAmount = businessTradeConfig.getTradeHedgeAmount();
                    }else{
                        tradeAmount = businessTradeConfig.getTradeHedgeAmount();
                        tradeReversAmount = businessTradeConfig.getTradeHedgeMainAmount();
                    }
                }
            }
        }
        List<BusinessTradeRecord> businessTradeRecordListByStrategyId = strategyRecordMap.get(strategyId);

        int alreadySize = 0;
        BigDecimal alreadyOpenAmount = BigDecimal.ZERO;
        if (Objects.nonNull(businessTradeRecordListByStrategyId)) {
            // 一次开仓多比数据，委托单号相同
            alreadySize = businessTradeRecordListByStrategyId.stream().collect(Collectors.groupingBy(BusinessTradeRecord::getDelegateCode)).keySet().size();
            alreadyOpenAmount = businessTradeRecordListByStrategyId.stream().map(item -> new BigDecimal(item.getDelegateVolume()).multiply(item.getPrice())).reduce(BigDecimal.ZERO, BigDecimal::add);
            // 判断单次或者单次分多比开仓后，需要等到单次开仓交易闭环结束后再次开仓
            boolean b = businessTradeRecordListByStrategyId.stream().allMatch(BusinessTradeRecord::getPositionClosed);
            if (!b) {
                return AjaxResult.error("策略ID:" + strategyId + " :当前仓还未触发平仓不可再次开仓");
            }
        }
        tradeAmountLimit = tradeAmountLimit.subtract(alreadyOpenAmount);
        if (tradeAmountLimit.compareTo(BigDecimal.ZERO) <= 0) {
            return AjaxResult.error("策略ID:" + strategyId + " :达到日开仓金额限额");
        }
        if (tradeAmountLimit.compareTo(tradeAmount) < 0) {
            tradeAmount = tradeAmountLimit;
        }

        BigDecimal positionVolume = tradeAmount.divide(price.multiply(new BigDecimal(100)), 0, BigDecimal.ROUND_CEILING).multiply(new BigDecimal(100));

        if (alreadySize >= tradeTimesLimit) {
            return AjaxResult.error("策略ID:" + strategyId + " :达到开仓次数限额");
        }
        // 首次下单
        if (orFirstTrade && openPosition) {
            if (alreadySize != 0) {
                return AjaxResult.error("策略ID:" + strategyId + " 已存在开仓数据,非首次下单");
            }
            // 如果单笔开仓金额折算股数大于 单笔股数限额 则分多比开仓
            BigDecimal timesPositionVolumeLeft = positionVolume;

            int openPositionVolum = 0;
            String delegateCode = UUID.randomUUID().toString().replaceAll("-", "");
            String delegateCodeRevers = "DC" + delegateCode;

            while (timesPositionVolumeLeft.compareTo(BigDecimal.ZERO) > 0) {
                int currPosition = Math.toIntExact(tradeVolumePerLimit);
                if (timesPositionVolumeLeft.compareTo(new BigDecimal(tradeVolumePerLimit)) <= 0) {
                    currPosition = timesPositionVolumeLeft.intValue();
                }
                doAutoTrade(strategyGroupId, strategyId, symbol, currPosition, takePositionPrice, psIceOrderType.value(), relatedOrderNo, delegateCode,clientName,password);
                timesPositionVolumeLeft = timesPositionVolumeLeft.subtract(new BigDecimal(currPosition));
                openPositionVolum += currPosition;

            }

            //开启对冲
            if (tradeHedge) {
                // 对冲金额计算开仓总股数

                BigDecimal timesReversVolumeLeft = tradeReversAmount.divide(price.multiply(new BigDecimal(100)), 0, BigDecimal.ROUND_CEILING).multiply(new BigDecimal(100));
                int openPositionReversVolume = 0;
                while (timesReversVolumeLeft.compareTo(BigDecimal.ZERO) > 0) {
                    int currPosition = Math.toIntExact(tradeVolumePerLimit);
                    if (timesReversVolumeLeft.compareTo(new BigDecimal(tradeVolumePerLimit)) <= 0) {
                        currPosition = timesReversVolumeLeft.intValue();
                    }
                    AjaxResult ajaxResult = doAutoTrade(strategyGroupId, strategyId, symbol, currPosition, takePositionPriceRevers, psIceOrderTypeRevers.value(), relatedOrderNo, delegateCodeRevers,clientName,password);
                    if ((int) ajaxResult.get(AjaxResult.CODE_TAG) == 200) {
                        timesReversVolumeLeft = timesReversVolumeLeft.subtract(new BigDecimal(currPosition));
                        openPositionReversVolume += currPosition;
                    }
                }
                logger.info("策略ID:" + strategyId + " :首次对冲开仓结束,委托价格：{},开仓总股数：{},开仓金额：{}", takePositionPriceRevers, openPositionReversVolume, tradeReversAmount);

            }

            logger.info("策略ID:" + strategyId + " :首次开仓结束,现价price:{},委托价格：{},开仓总股数：{},开仓金额：{}", price, takePositionPrice, openPositionVolum, tradeAmount);
            return AjaxResult.success();

        } else if (!orFirstTrade) {
            // 计算剩余可开仓总量
            positionVolume = tradeAmount.divide(takePositionPrice.multiply(new BigDecimal(100)), 0, BigDecimal.ROUND_CEILING).multiply(new BigDecimal(100));

            // 多次开仓
            BigDecimal timesPositionVolumeLeft = positionVolume;

            int openPositionVolum = 0;
            String delegateCode = UUID.randomUUID().toString().replaceAll("-", "");

            while (timesPositionVolumeLeft.compareTo(BigDecimal.ZERO) > 0) {
                int currPosition = Math.toIntExact(tradeVolumePerLimit);
                if (timesPositionVolumeLeft.compareTo(new BigDecimal(tradeVolumePerLimit)) <= 0) {
                    currPosition = timesPositionVolumeLeft.intValue();
                }

                doAutoTrade(strategyGroupId, strategyId, symbol, currPosition, takePositionPrice, psIceOrderType.value(), relatedOrderNo, delegateCode,clientName,password);
                timesPositionVolumeLeft = timesPositionVolumeLeft.subtract(new BigDecimal(currPosition));
                openPositionVolum += currPosition;
            }
            logger.info("策略ID:" + strategyId + " :再次开仓结束,现价price:{},委托价格：{},开仓总股数：{},开仓金额：{}", price, takePositionPrice, openPositionVolum, tradeAmount);
            return AjaxResult.success();
        }

        return null;
    }

    private AjaxResult doAutoTrade(Long strategyGroupId, Long strategyId, String symbol, int intValue, BigDecimal takePositionPrice, int value, String relatedOrderNo, String delegateCode,String clientName,String password ) {

        BusinessTradeRecord businessTradeRecord = new BusinessTradeRecord();
        businessTradeRecord.setStrategyGroupId(strategyGroupId);
        businessTradeRecord.setDelegateCode(delegateCode);
        businessTradeRecord.setStrategyId(strategyId);
        businessTradeRecord.setStockCode(symbol);
        businessTradeRecord.setDelegateVolume(intValue);
        businessTradeRecord.setPrice(takePositionPrice);
        businessTradeRecord.setDelegateType(value);
        businessTradeRecord.setClientName(clientName);
        businessTradeRecord.setPassword(password);
        if (StringUtils.isNotEmpty(relatedOrderNo)) {
            businessTradeRecord.setRelatedOrderNo(relatedOrderNo);
        }
        businessTradeRecord.setTriggerType(TriggerType.AUTO_TAKE_POSITION_TRIGGER.toString());
        return tradeAndInsertBusinessTradeRecord(businessTradeRecord);

    }

    @Override
    public RateStatisticsDTO winRateStatistics(String type) {

        RateStatisticsDTO rateStatisticsDTO = new RateStatisticsDTO();

        List<SeriesDTO> seriesDTOS = new ArrayList<>();

        List<Map<String, Object>> strategyGroupList = new ArrayList<>();

        List<SysDictData> businessStrategyGroup = sysDictDataMapper.selectDictDataByType("business_strategy_group");
        if (CollectionUtils.isEmpty(businessStrategyGroup)) {
            throw new TradeException("分组字典数据为空");
        }
        Map<String, SysDictData> strategyGroupMap = businessStrategyGroup.stream().collect(Collectors.toMap(SysDictData::getDictValue, Function.identity()));

        List<BusinessTradeConfig> businessTradeConfigs = businessTradeConfigMapper.selectBusinessTradeConfigList(new BusinessTradeConfig());

        if (businessTradeConfigs.size() == 0) {
            throw new TradeException("配置策略参数不存在");
        }

        Map<Long, BusinessTradeConfig> businessTradeConfigMap = businessTradeConfigs.stream().collect(Collectors.toMap(BusinessTradeConfig::getId, Function.identity()));


        List<BusinessTradeRecord> tradeRecordList = businessTradeRecordMapper.selectBusinessTradeRecordEffec();
        //根据时间进行升序排序
        Map<String, List<BusinessTradeRecord>> businessTradeMap = new LinkedHashMap<>();
        tradeRecordList.stream().collect(Collectors.groupingBy(item -> DateUtils.dateTime(item.getCreateTime()))).entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(x -> businessTradeMap.put(x.getKey(), x.getValue()));
        Set<String> dates = businessTradeMap.keySet();
        rateStatisticsDTO.setxAxisData(dates);
        rateStatisticsDTO.setStrategyGroupList(strategyGroupList);

        // 赢利率

        List<BusinessTradeRecord> openOrders = tradeRecordList.stream().filter(BusinessTradeRecord::getPositionClosed).filter(item -> TriggerType.AUTO_TAKE_POSITION_TRIGGER.equals(TriggerType.valueOf(item.getTriggerType()))).collect(Collectors.toList());

        Map<Long, List<BusinessTradeRecord>> strategyGroupRecordMap = openOrders.stream().collect(Collectors.groupingBy(BusinessTradeRecord::getStrategyGroupId));

        Set<String> legend = new HashSet<>();
        strategyGroupRecordMap.forEach((strategyGroupId, businessTradeRecordList) -> {
            SysDictData sysDictData = strategyGroupMap.get(String.valueOf(strategyGroupId));
            if (Objects.isNull(sysDictData)) {
                throw new TradeException("未获取到策略分组数据");
            }
            Map<String, Object> objectObjectHashMap = new HashMap<>();
            objectObjectHashMap.put("id", strategyGroupId);
            objectObjectHashMap.put("name", sysDictData.getDictLabel());
            strategyGroupList.add(objectObjectHashMap);


            Map<Long, List<BusinessTradeRecord>> strategyGroupIdAndStrategyIdRecordMap = businessTradeRecordList.stream().collect(Collectors.groupingBy(BusinessTradeRecord::getStrategyId));


            for (Map.Entry<Long, List<BusinessTradeRecord>> longListEntry : strategyGroupIdAndStrategyIdRecordMap.entrySet()) {
                Long strategyId = longListEntry.getKey();
                List<BusinessTradeRecord> groupIdAndStrategyIdRecordList = longListEntry.getValue();

                List<Double> dataList = new ArrayList<>();
                SeriesDTO seriesDTO = new SeriesDTO();
                seriesDTO.setType("line");
                seriesDTO.setStrategyGroupId(strategyGroupId);
//                seriesDTO.setStack("Total");
                seriesDTO.setName("策略名称 " + businessTradeConfigMap.get(strategyId).getStrategyName());
                legend.add(seriesDTO.getName());

                for (String date : dates) {


                    List<BusinessTradeRecord> currentDateAndGroupStrategyIdRecord = groupIdAndStrategyIdRecordList.stream().filter(item -> DateUtils.dateTime(item.getCreateTime()).equals(date)).collect(Collectors.toList());
                    // 赢利率
                    if (TradeConstants.ECHARTS_PROFIT_RATE.equals(type)) {
//                        BigDecimal dayOpenAmount = currentDateAndGroupStrategyIdRecord.stream().map(BusinessTradeRecord::getDealAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
//                        // 回单成交金额
//                        BigDecimal backOrderDealAmountAll = BigDecimal.ZERO;
//                        for (BusinessTradeRecord openOrder : currentDateAndGroupStrategyIdRecord) {
//                            List<BusinessTradeRecord> collect = tradeRecordList.stream().filter(item -> !TriggerType.AUTO_TAKE_POSITION_TRIGGER.equals(TriggerType.valueOf(item.getTriggerType())))
//                                    .filter(item -> item.getRelatedOrderNo().equals(openOrder.getOrderNo())).collect(Collectors.toList());
//                            if (collect.size() != 1) {
//                                logger.error("统计查询开仓单据对应回单 不存在或有多条，collect.size:{}", collect.size());
//                                continue;
//                            }
//                            //获得回单
//                            BusinessTradeRecord businessTradeRecord = collect.get(0);
//                            BigDecimal backOrderDealAmount = businessTradeRecord.getDealAmount() == null ? BigDecimal.ZERO : businessTradeRecord.getDealAmount();
//                            backOrderDealAmountAll = backOrderDealAmountAll.add(backOrderDealAmount);
//                        }

//                        BigDecimal subtract = dayOpenAmount.subtract(backOrderDealAmountAll);
//                        double profitRate = 0.00;
//                        if (dayOpenAmount.compareTo(BigDecimal.ZERO) > 0) {
//                            profitRate = subtract.divide(dayOpenAmount, 5, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).doubleValue();
//                        }
                        //计算策略赢利率  （总收益除总开仓）
                        currentDateAndGroupStrategyIdRecord = currentDateAndGroupStrategyIdRecord.stream().filter(item -> Objects.nonNull(item.getProfitRate())).collect(Collectors.toList());
                        BigDecimal allProfitRate = new BigDecimal(0);
                        if (!currentDateAndGroupStrategyIdRecord.isEmpty()) {
                            BigDecimal allProfit = currentDateAndGroupStrategyIdRecord.stream().map(BusinessTradeRecord::getProfit).reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal allDealAmount = currentDateAndGroupStrategyIdRecord.stream().map(BusinessTradeRecord::getDealAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                            allProfitRate = allProfit.divide(allDealAmount,6,RoundingMode.HALF_UP).multiply(new BigDecimal("100"));

                        }
                        dataList.add(allProfitRate.doubleValue());
                    }

                    // 赢次率
                    if (TradeConstants.ECHARTS_TIMES_RATE.equals(type)) {
                        // 盈利次数
                        List<BusinessTradeRecord> profitPositionRecords = currentDateAndGroupStrategyIdRecord.stream().filter(item -> (item.getProfitRate() == null ? BigDecimal.ZERO : item.getProfitRate()).compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                        int count = profitPositionRecords.stream().collect(Collectors.groupingBy(BusinessTradeRecord::getDelegateCode)).keySet().size();
                        BusinessTradeConfig businessTradeConfig = businessTradeConfigMap.get(strategyId);
                        if (Objects.isNull(businessTradeConfig)) {
                            logger.error("统计查询开仓单据对应策略 不存在");
                            continue;
                        }
                        Double winningRate = new BigDecimal(count).divide(new BigDecimal(businessTradeConfig.getTradeTimesLimit()), 5, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).doubleValue();
                        dataList.add(winningRate);
                    }
                    seriesDTO.setData(dataList);
                }
                seriesDTOS.add(seriesDTO);
            }

        });
        rateStatisticsDTO.setLegend(legend);
        rateStatisticsDTO.setSeriesDTOList(seriesDTOS);
        return rateStatisticsDTO;
    }
}
